//
//  ShionAppDelegate.m
//  Shion
//
//  Created by Chris Karr on 12/17/07.
//  Copyright 2007-2008 Audacious Software. All rights reserved.
//

#import "ShionAppDelegate.h"
#import "DevicesModel.h"
#import "Device.h"
#import "Snapshot.h"

#import "AppleScriptDevice.h"
#import "AppleScriptSnapshot.h"

#include "IdleTime.h"
#include "LoginItemsAE.h"

#define START_AT_LOGIN @"start_at_login"

#define SHION_DEVICES @"Shion: Devices"
#define SHION_SNAPSHOTS @"Shion: Snapshots"

#define HIDE_STATUS_ICON @"Hide Status Icon"

@implementation ShionAppDelegate

- (void) load
{
	NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
	
	NSArray * deviceArray = [defaults arrayForKey:SHION_DEVICES];
	
	if (deviceArray != nil && [deviceArray count] > 0)
	{
		for (NSDictionary * dict in deviceArray)
		{
			Device * device = [[Device alloc] init];
			
			device.name = [dict valueForKey:@"Device Name"];
			device.address = [dict valueForKey:@"Device Address"];
			device.dimmer = [[dict valueForKey:@"Dimmer"] boolValue];
			
			[devices addObject:device];
		}
	}
	else
	{
		Device * device = [[Device alloc] init];
		device.name = @"New Device";

		[devices addObject:device];
	}
	
	[devices selectNext:nil];
	[devices selectPrevious:nil];

	NSArray * snapArray = [defaults arrayForKey:SHION_SNAPSHOTS];
	
	if (snapArray != nil)
	{
		for (NSDictionary * dict in snapArray)
		{
			Snapshot * snapshot = [[Snapshot alloc] init];

			snapshot.name = [dict valueForKey:@"Snapshot Name"];
			snapshot.activateEvent = [dict valueForKey:@"Activation Event"];
			
			snapshot.deviceStates = [NSMutableSet setWithArray:[dict valueForKey:@"Device States"]];
			
			for (NSDictionary * dict in snapshot.deviceStates)
			{
				NSInteger level = [[dict valueForKey:@"level"] integerValue];
				
				if (level == 0)
					[dict setValue:@"Off" forKey:@"levelString"];
				else if (level < 255)
					[dict setValue:[NSString stringWithFormat:@"%d", ((level + 1) / 32)] forKey:@"levelString"];
				else
					[dict setValue:@"On" forKey:@"levelString"];
			}
			
			[snapshots addObject:snapshot];
		}
	}
	
	[snapshots selectNext:nil];
	[snapshots selectPrevious:nil];
}

- (void) save
{
	NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
	
	NSMutableArray * saveArray = [NSMutableArray array];

	for (Device * device in [devices arrangedObjects])
	{
		NSMutableDictionary * dict = [NSMutableDictionary dictionary];
		
		[dict setValue:device.name forKey:@"Device Name"];
		[dict setValue:device.address forKey:@"Device Address"];
		[dict setValue:[NSNumber numberWithBool:device.dimmer] forKey:@"Dimmer"];
		
		[saveArray addObject:dict];
	}
	
	[defaults setValue:saveArray forKey:SHION_DEVICES];

	NSMutableArray * snapArray = [NSMutableArray array];

	for (Snapshot * snapshot in [snapshots arrangedObjects])
	{
		NSMutableDictionary * dict = [NSMutableDictionary dictionary];
		
		[dict setValue:snapshot.name forKey:@"Snapshot Name"];
		[dict setValue:[snapshot.deviceStates allObjects] forKey:@"Device States"];
		[dict setValue:snapshot.activateEvent forKey:@"Activation Event"];
		
		[snapArray addObject:dict];
	}
	
	[defaults setValue:snapArray forKey:SHION_SNAPSHOTS];

}

- (void) statusIcon
{
	if (![[NSUserDefaults standardUserDefaults] boolForKey:@"Hide Status Icon"])
	{
		NSStatusBar * bar = [NSStatusBar systemStatusBar];
 
		if (theItem == nil)
			[theItem release];
			
		theItem = [bar statusItemWithLength:NSVariableStatusItemLength];
		[theItem retain];

		[theItem setTitle:nil];
		[theItem setImage:[NSImage imageNamed:@"cache-menu-off"]];
		[theItem setAlternateImage:[NSImage imageNamed:@"cache-menu-on"]];
		[theItem setHighlightMode:YES];
		[theItem setMenu:menu];
	}
	else
		[[NSStatusBar systemStatusBar] removeStatusItem:theItem];
}

- (void) indigoCheck
{
	if ([[NSFileManager defaultManager] fileExistsAtPath:@"/System/Library/Extensions/IndigoOverrides.kext"])
	{
		NSRunAlertPanel(@"Indigo Kernel Extensions Located", @"Shion cannot run until while Indigo is installed.", @"More Info...", nil, nil);
		
		[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:[[[NSBundle mainBundle] infoDictionary] valueForKey:@"IndigoFixURL"]]];
	}
}

- (void) awakeFromNib
{
	[self indigoCheck];
	
	[self statusIcon];
	
	[devices addObserver:self forKeyPath:@"selection" options:0 context:NULL];
	[devices addObserver:self forKeyPath:@"arrangedObjects" options:0 context:NULL];

	[snapshots addObserver:self forKeyPath:@"arrangedObjects" options:0 context:NULL];

	[[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:HIDE_STATUS_ICON options:NSKeyValueObservingOptionNew context:NULL];
	[[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:START_AT_LOGIN options:0 context:NULL];

	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(addDevice:) name:ADD_DEVICE object:nil];
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(removeDevice:) name:REMOVE_DEVICE object:nil];
	
	[self load];
}

- (void) startAtLogin
{
	BOOL enabled = [[NSUserDefaults standardUserDefaults] boolForKey:START_AT_LOGIN];
	
	NSLog (@"start at login = %d", enabled);
	
	OSStatus status;
	CFArrayRef loginItems = NULL;
	NSURL * url = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
	
	int existingLoginItemIndex = -1;
	
	status = LIAECopyLoginItems (&loginItems);
	
	if (status == noErr) 
	{
		NSEnumerator * enumerator = [(NSArray *) loginItems objectEnumerator];
		NSDictionary * loginItemDict;
		
		while ((loginItemDict = [enumerator nextObject])) 
		{
			if ([[loginItemDict objectForKey:(NSString *) kLIAEURL] isEqual:url]) 
			{
				existingLoginItemIndex = [(NSArray *) loginItems indexOfObjectIdenticalTo:loginItemDict];
				break;
			}
		}
	}
	
	if (enabled && (existingLoginItemIndex == -1))
		LIAEAddURLAtEnd ((CFURLRef) url, false);
	else if (!enabled && (existingLoginItemIndex != -1))
		LIAERemove (existingLoginItemIndex);
	
	if (loginItems)
		CFRelease (loginItems);
}

- (void)observeValueForKeyPath:(NSString *) keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqual:@"selection"]) 
	{
		if ([[devices selectedObjects] count] > 0)
		{
			Device * device = [[devices selectedObjects] objectAtIndex:0];
			
			if (device.dimmer)
				[slider setNumberOfTickMarks:9];
			else
				[slider setNumberOfTickMarks:2];
				
			if (device.actualStatus.lightLevel != nil)
				[slider setIntegerValue:[device.actualStatus.lightLevel integerValue]];
			else
				[slider setIntegerValue:0];
				
			[webView updateDeviceInfo];
		}
		else
			[slider setEnabled:NO];
	}
	else if ([keyPath isEqual:@"arrangedObjects"] && object == devices) 
	{
		if (asDevices != nil)
			[asDevices release];
			
		asDevices = nil;
	}
	else if ([keyPath isEqual:@"arrangedObjects"] && object == snapshots) 
	{
		if (asSnapshots != nil)
			[asSnapshots release];
			
		asSnapshots = nil;
	}
	else if ([keyPath isEqual:HIDE_STATUS_ICON]) 
		[self statusIcon];
	else if ([keyPath isEqual:START_AT_LOGIN])
		[self startAtLogin];
}

- (IBAction) edit:(id) sender
{
	[NSApp beginSheet:editPanel modalForWindow:window modalDelegate:self didEndSelector:nil contextInfo:NULL];
}

- (IBAction) quitEdit:(id) sender
{
	[NSApp endSheet:editPanel];
	[editPanel orderOut:self];
}

- (IBAction) remove:(id) sender
{
	[devices remove:sender];
}

- (IBAction) newDocument:(id) sender
{
	[self devicesWindow:sender];
	
	Device * device = [[Device alloc] init];
	device.name = @"New Device";

	[devices addObject:device];

	[self edit:sender];
} 

- (void) addDevice:(NSNotification *) theNote
{
	NSDictionary * userInfo = [theNote userInfo];

	Device * device = [[Device alloc] init];
	device.name = [userInfo valueForKey:NAME];
	[device setAddressString:[userInfo valueForKey:ADDRESS]];
	
	NSNumber * dimmer = [userInfo valueForKey:DIMMER];
	
	if (dimmer != nil && [dimmer boolValue])
		device.dimmer = YES;
	
	[devices addObject:device];
	[self save];
}

- (void) removeDevice:(NSNotification *) theNote
{
	NSDictionary * userInfo = [theNote userInfo];
	
	Device * device = [userInfo objectForKey:DEVICE];

	[devices removeObject:device];
	[self save];
}

- (IBAction) new:(id) sender
{
	[self newDocument:sender];
}

- (BOOL) applicationShouldTerminateAfterLastWindowClosed: (NSApplication *)theApplication
{
	return NO;
}

- (void)applicationWillTerminate:(NSNotification *)aNotification
{
 	[self save];
}

- (IBAction) preferences:(id) sender
{
	[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
	[preferences makeKeyAndOrderFront:sender];
}

- (IBAction) devicesWindow:(id) sender
{
	[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
	[window makeKeyAndOrderFront:sender];
}

- (IBAction) snapshots:(id) sender
{
	[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
	[snapshotWindow makeKeyAndOrderFront:sender];
}

- (void) applicationWillBecomeActive:(NSNotification *) aNotification 
{
	[[NSNotificationCenter defaultCenter] postNotificationName:SHION_SYNCNOW object:self];
}

- (void)applicationWillResignActive:(NSNotification *)aNotification 
{

}

- (BOOL)application:(NSApplication *) sender delegateHandlesKey:(NSString *) key
{
	if ([key isEqualToString:@"devices"])
		return YES;
	else if ([key isEqualToString:@"snapshots"])
		return YES;
	else if ([key isEqualToString:@"remove"])
		return YES;

	return NO;
}

- (NSArray *) getDevices
{
	if (asDevices == nil)
	{
		asDevices = [[NSMutableArray alloc] init];
	
		for (Device * d in [devices arrangedObjects])
		{
			AppleScriptDevice * asd = [[AppleScriptDevice alloc] init];

			asd.device = d;
			
			[asDevices addObject:asd];
		}
	}
	
	return asDevices;
}

- (NSArray *) getSnapshots
{
	if (asSnapshots == nil)
	{
		asSnapshots = [[NSMutableArray alloc] init];
	
		for (Snapshot * s in [snapshots arrangedObjects])
		{
			AppleScriptSnapshot * ass = [[AppleScriptSnapshot alloc] init];

			ass.snapshot = s;
			
			[asSnapshots addObject:ass];
		}
	}
	
	return asSnapshots;
}

- (IBAction) newSnapshot:(id) sender
{
	[self snapshots:sender];
	
	[snapshots add:sender];
}

- (IBAction) openWebSite:(id) sender
{
	[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:[[[NSBundle mainBundle] infoDictionary] valueForKey:@"ShionWebHome"]]];
}


@end
